package seu.evaluation.metric;


import java.util.ArrayList;

import seu.xml.analysis.UMLERDiagram;
import seu.xml.analysis.UMLEntity;
import seu.xml.analysis.UMLRelation;
/**
 * 
 * @author samantha
 * 该类功能：解析--maintainability的度量所需要的元素
 * N:图中组件的个数
 * L:layer,UML图的个数，通常为1
 * totalE:整个图的边的数目
 * N,L，totalE针对整个图，而非某个构件
 *
 */
public class MaintainabilityDiagram {

	private int N;
	private int L;
	private int totalE;
	private ArrayList<MaintainabilityEntity> listEntity;
	private ArrayList<Integer> externalEntity; //非子组件 
	private UMLERDiagram umlDiagram;

	
	public MaintainabilityDiagram(UMLERDiagram umlDiagram){
		N=0;
		L=1;
		totalE=0;
		listEntity=new ArrayList<MaintainabilityEntity>();
		externalEntity = new ArrayList<Integer>();
		this.umlDiagram = umlDiagram;

		/**
		 * 计算组件图的边数之和，不包括组件内部的边
		 */
		for(UMLRelation relation : umlDiagram.ur){		
			if( relation.externalEntity.size()==0 ){
				totalE++;
				if( relation.UMLRelationElement.getPanel_attributes().startsWith("lt=())") )
					totalE++;
			}
		}
	
		/**
		 * 计算组件图中的组件个数，不包括子组件
		 */
		for( UMLEntity entity : umlDiagram.ue ){
			if( entity.externalEntity.size()==0 ){
				externalEntity.add( entity.getId() );
				N++;
			}
		}
	
		for( UMLEntity entity : umlDiagram.ue ){
			/**
			 * 针对每个组件，设置其ID和name
			 */		
			MaintainabilityEntity umlEntityMeta = new MaintainabilityEntity();
			umlEntityMeta.setID(entity.getId());
			String entityName = entity.UMLEntityElement.getPanel_attributes().replace("\n","");
			entityName = entityName.replace("'","");			
			umlEntityMeta.setName( entityName );
			
			/**
			 * 针对每个组件，计算子组件的个数,并将该子组件加入到集合中
			 */
			umlEntityMeta.setS(0);
			for( int id : entity.internalEntity ){
				for( UMLEntity inEntity : umlDiagram.ue ){
					if( id == inEntity.getId()){					
						boolean isInternal =true;
						for( int tempID : entity.internalEntity  ){
							if( inEntity.externalEntity.contains(tempID)){
								isInternal=false;
								break;
							}
						}	
						if( isInternal ){
							umlEntityMeta.setS(umlEntityMeta.getS()+1);	
							umlEntityMeta.getInNode().add( id);
						}
					}
				}
			}
			
			/**
			 * 针对每个组件，计算其子组件相互连接的边数
			 * 将该边存入临时变量eArray
			 */
			ArrayList<Integer> eArray = new ArrayList<Integer>();
			umlEntityMeta.setInterEdge(0);
			for( int rID : entity.internalRelation ){
				Boolean isInternal = true;
				for( int eID : entity.internalEntity ){
					UMLEntity inEntity = umlDiagram.ue.get(eID);
					if( inEntity.internalRelation.contains(rID) ){
						isInternal = false;
						break;
					}
				}
				if( isInternal == true){
					umlEntityMeta.setInterEdge( umlEntityMeta.getInterEdge()+1 );	
					eArray.add(rID);
				}
			}	
			
			/**
			 * 针对每个组件，初始化内部组件连接数组
			 */
			int s = umlEntityMeta.getS();
			if( s!=0 ){
			int a[][] = new int[s][s];
			for( int rID : eArray ){
				UMLRelation r = umlDiagram.ur.get(rID);
				/** 
				 * 虚线箭头（依赖关系）
				 *  */
				if( r.UMLRelationElement.getPanel_attributes().startsWith("lt=<.") ){
					int startID = -1;
					int endID = -1;
					int size = umlEntityMeta.getInNode().size();
					for( int i=0; i<size; i++ ){
						if( umlEntityMeta.getInNode().get(i)==r.getEndEntityID() )
							startID = i;
						if( umlEntityMeta.getInNode().get(i)==r.getStartEntityID() )
							endID = i;
					}
					a[startID][endID]++;
				}
			}
			umlEntityMeta.setTransitiveClosure( a );
			}
	
			
			umlEntityMeta.setE(0);
			umlEntityMeta.setX(0);
			umlEntityMeta.setR(0);
			umlEntityMeta.setW(0);		
			listEntity.add(umlEntityMeta);		
		}
		
		/**
		 * 计算每个组件的出入边
		 */
		for( UMLRelation r : umlDiagram.ur ){
			int startID = r.getStartEntityID();
			int endID= r.getEndEntityID();
			if( startID >= 0){
				UMLEntity se = umlDiagram.ue.get(startID);
				setEntityEdge(r, se);
			}
			if( endID >= 0){
				UMLEntity ee = umlDiagram.ue.get(endID);
				setEntityEdge(r, ee);
			}			
		}	
			
		print();
	}
	
	public void setEntityEdge( UMLRelation r, UMLEntity e){
		String panelAttribute = r.UMLRelationElement.getPanel_attributes();
		Boolean isX = false;
		Boolean isE = false;
		Boolean isW = false;
		Boolean isR = false;
		/** 
		 * 虚线箭头（依赖关系）
		 *  */
		if( panelAttribute.startsWith("lt=<.") ){
			if( r.getStartEntityID()==e.getId() )
				isX = true;
			else
				isE = true;
		}
		/**
		 * 接口，双方
		 */
		else if( panelAttribute.startsWith("lt=())") ){
			if( r.getStartEntityID()== e.getId() )
				isW = true;
			else
				isR = true;							
		}
		/**
		 * 提供接口方
		 */
		else if( panelAttribute.startsWith("lt=<()") ){
			if( r.getEndEntityID() == e.getId() )
				isW = true;			
		}
		/**
		 * 使用接口方
		 */
		else if( panelAttribute.startsWith("lt=<(") ){
			if( r.getEndEntityID() == e.getId() )
				isR = true;
		}
		else
			;
		
		ArrayList<MaintainabilityEntity> meList = new ArrayList<MaintainabilityEntity>();
		meList.add(  listEntity.get(e.getId()) );
		
		for( int outID : e.externalEntity ){
			UMLEntity outEntity = umlDiagram.ue.get( outID );
			if( !outEntity.internalRelation.contains(r.getId()) ){
				MaintainabilityEntity outME = listEntity.get( outID );
				meList.add( outME );
			}		
		}
		
		for( MaintainabilityEntity me : meList ){
			if( isX )
				me.setX( me.getX()+1 );
			else if( isE )
				me.setE( me.getE()+1 );
			else if( isW )
				me.setW( me.getW()+1 );
			else if( isR )
				me.setR( me.getR()+1 );
			else
				;
		}

	}
	
	
	public int getN(){
		return this.N;
	}
	
	public int getL(){
		return this.L;
	}
	
	public int getTotalE(){
		return this.totalE;
	}
	
	public  ArrayList<MaintainabilityEntity> getListEntity(){
		return this.listEntity;
	}
	
	public ArrayList<Integer> getExternalEntity(){
		return this.externalEntity;
	}
	
	public void print(){
		System.out.println("***************解析***************");
		System.out.println("N: "+N);
		System.out.println("totalE: "+totalE);
		System.out.println("L: "+L);
		for( MaintainabilityEntity em : listEntity){			
			System.out.println("componentID: "+em.getComponentID()+"  name: "+em.getName()+
					"  S: "+em.getS()+"  E: "+em.getE()+"  X: "+em.getX()+"  R: "+em.getR()+
					"  W: "+em.getW()+"  internalEdge: "+em.getInterEdge());
		
			System.out.println("array:");
			for( int i=0; i<em.getS();i++){
				for( int j=0; j<em.getS(); j++){
					System.out.print( (em.getTransitiveClosure())[i][j] +"  " );
				}
				System.out.println();
			}
		}
		System.out.println("***************解析结束***************");
	}
	
}
